use crate::models::CRUD;
use diesel::PgConnection;
use crate::schema::user_infos;
use diesel::{RunQueryDsl, prelude::*, result::Error, Insertable, Queryable};


#[derive(Queryable, Debug, Serialize)]
pub struct UserInfo {
    pub id: i32,
    pub uid: i32,
    pub sex: Option<String>,
    pub address: Option<String>,
    pub school: Option<String>,
    pub remark: Option<String>,
}


#[derive(Debug, Insertable, AsChangeset, Serialize, Deserialize)]
#[table_name = "user_infos"]
pub struct NewUserInfo {
    pub uid: i32,
    pub sex: Option<String>,
    pub address: Option<String>,
    pub school: Option<String>,
    pub remark: Option<String>,
}

impl UserInfo{
    pub fn get_by_uid(conn: &PgConnection, uid: i32) -> Result<Self, Error> {
        user_infos::table.filter(user_infos::uid.eq(uid)).first::<UserInfo>(conn)
    }
}

impl CRUD<NewUserInfo, NewUserInfo, i32> for UserInfo {
    fn create(conn: &PgConnection, from: &NewUserInfo) -> Result<Self, Error> where
        Self: Sized {
        diesel::insert_into(user_infos::table).values(from).get_result(conn)
    }

    fn read(conn: &PgConnection, page: i64, page_size: i64) -> Vec<Self> where
        Self: Sized {
        user_infos::table
            .order(user_infos::id.asc())
            .limit(page_size)
            .offset((page - 1) * page_size)
            .load::<UserInfo>(conn).unwrap_or(vec![])
    }

    fn update(conn: &PgConnection, pk: i32, value: &NewUserInfo) -> Result<Self, Error> where
        Self: Sized {
        diesel::update(user_infos::table.find(pk))
            .set(value)
            .get_result(conn)
    }

    fn delete(conn: &PgConnection, pk: i32) -> Result<usize, Error> where
        Self: Sized {
        diesel::delete(user_infos::table.filter(user_infos::id.eq(pk)))
            .execute(conn)
    }

    fn get_by_pk(conn: &PgConnection, pk: i32) -> Result<Self, Error> where
        Self: Sized {
        user_infos::table.find(pk).first::<UserInfo>(conn)
    }
}

mod form {
    use crate::models::user::form::NewUserForm;
    use crate::models::user_info::NewUserInfo;

    impl From<NewUserForm> for NewUserInfo {
        fn from(form: NewUserForm) -> Self {
            Self {
                uid: 0,
                sex: form.sex,
                address: form.address,
                school: form.school,
                remark: form.remark,
            }
        }
    }
}
